package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type Student struct {
	Id    int16
	Name  string
	Score float64
	Sex   string
	//DeletedAt gorm.DeletedAt
}

//对数据库的读操作

func main() {
	dsn1 := "root:root@tcp(127.0.0.1:3306)/userdb?charset=utf8mb4&parseTime=True&loc=Local"
	gormDB, err := gorm.Open(mysql.Open(dsn1), &gorm.Config{})
	if err != nil {
		fmt.Println("gorm.Open Error :", err)
	}
	//单条查询
	/*
		GORM 提供了三个方法，分别是 First、Last 和 Take，其中 First 和 Last 是根据主键升序和降序，使用 Limit 1 获取 1 条记录。
		Take 方法未指定排序字段，使用 Limit 1获取 1 条记录，排序规则根据数据库的实现。
	*/
	//First 方法：
	student := Student{}
	gormDB.First(&student)
	fmt.Println(student)
	//Take 方法：
	student = Student{}
	gormDB.Take(&student)
	fmt.Println(student)
	//Last 方法：
	student = Student{}
	result := gormDB.Last(&student)
	fmt.Println(student)
	fmt.Printf("实现了%d结果,Error %v\n", result.RowsAffected, result.Error)

	//查询所有
	//关于查询所有记录，GORM 提供了 Find 方法，获取全部记录。
	var students []Student
	result = gormDB.Find(&students)
	fmt.Println(students)
	fmt.Printf("得出了%d结果,Error %v\n", result.RowsAffected, result.Error)

	//条件查询
	//GORM 提供了 Where、Not 和 Or 方法。其中 Where 方法分别可以通过使用 String 条件、Struct 条件、Map 条件和主键 Slice 条件。
	//需要特别注意的是，当使用 Struct 条件时，GORM 只会查询非零值字段，也就是说如果你的字段是该字段类型的零值，
	//将不会被用于构建查询条件。如果需要使用零值构建查询条件，可以使用 Map 构建查询条件。

	//Where 方法
	//String 条件：
	student = Student{}
	gormDB.Where("name = ?", "lsx").First(&student)
	fmt.Println("1", student)

	gormDB.Where("name <> ?", "fmx").Find(&students)
	fmt.Println("2", students)

	gormDB.Where("name IN ?", []string{"fmx", "lsx"}).Find(&students)
	fmt.Println("3", students)

	gormDB.Where("name LIKE ?", "%x%").Find(&students)
	fmt.Println("4", students)

	gormDB.Where("name = ? AND score > ?", "fmx", 90).Find(&students)
	fmt.Println("5", students)

	// lastWeek := time.Now().Add(time.Hour * 24 * -7)
	// gormDB.Where("updated_at > ?", lastWeek).Find(&students)
	// fmt.Println("6", students)
	// lastWeek := time.Now().Add(time.Hour*24*-7)
	// today := time.Now()
	// gormDB.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&students)
	// fmt.Println(students)

	//Struct 条件：
	var stus []Student
	gormDB.Where(&Student{Name: "", Score: 99.99}).Find(&stus) //若有字段是零值就不作为条件
	fmt.Println("6", stus)

	//Map 条件：
	gormDB.Where(map[string]interface{}{"name": "", "score": 89}).Find(&stus) //即使有字段是零值就也作为条件
	fmt.Println("7", stus)

	//主键 Slice 条件：
	gormDB.Where([]int{1, 3, 4}).Find(&stus)
	fmt.Println("8", stus)

	//Not 方法：
	//普通 Not 条件：
	gormDB.Not("name = ?", "fmx").First(&student)
	fmt.Println("11", student)

	//Not In：
	gormDB.Not(map[string]interface{}{"id": []int{1, 2}, "name": ""}).Find(&stus) //用map进行多条件判断
	fmt.Println("12", stus)

	//Struct：
	gormDB.Not(Student{Name: "fmx", Score: 99.99}).Find(&stus) //通过struct多条件判断
	fmt.Println("13", stus)

	//主键 Slice：
	gormDB.Not([]int{1, 2, 3}).Find(&stus)
	fmt.Println("14", stus)

	//Or 方法：
	//普通 Or：
	gormDB.Where("name = ?", "fmx").Or("name = ?", "lsx").Find(&stus)
	fmt.Println("21", stus)

	//Struct：
	gormDB.Where("name = ?", "fmx").Or(Student{Name: "fxl", Score: 99.99}).Find(&stus)
	fmt.Println("22", stus)

	//Map：
	gormDB.Where("name = ?", "").Or(map[string]interface{}{"name": "fxl", "score": 99.99}).Find(&stus)
	fmt.Println("23", stus)

	//按指定字段查找,只要某些字段
	//普通方式：
	gormDB.Select("name", "score").Find(&stus)
	fmt.Println("31", stus)

	//Slice 方式：
	gormDB.Select([]string{"name", "sex"}).Find(&stus)
	fmt.Println("32", stus)

	//
	//order 排序
	//普通方式：
	gormDB.Order("id desc, score").Find(&stus)
	fmt.Println("41", stus)

	//多个排序字段：
	gormDB.Order("id desc").Order("score").Find(&stus)
	fmt.Println("42", stus)

	//Limit & Offset  限制查询的条数，和偏移查询记录的开始位置。
	gormDB.Limit(2).Offset(1).Find(&stus)
	fmt.Println(stus)
}
